#!/usr/bin/env python3
import os

# ----------------------- [PORTS & INTERFACE] -----------------------
INTERFACE = "ens3"
WG_PORT = "58548"
DNS_PORT = "5353"
# ----------------------- [ADDRESS] -----------------------
ADDRESS = "10.66.66.1/24" # На 10.8.0.1/24 - странно не работет, а на 10.66.66.1/24 работает
CLIENT_1_ADDRESS = "10.66.66.2/32"
CLIENT_1_DNS_ADDRESS = "10.66.66.2/24"

CLIENT_2_ADDRESS = "10.66.66.3/32"
CLIENT_2_DNS_ADDRESS = "10.66.66.3/24"

# ----------------------- [WireGuard] -----------------------
# Install wireguard
print("[START INSTALL WIREGUARD]")
os.system("sudo apt-get update && apt upgrade -y")
os.system("apt install wireguard iptables net-tools wireguard-dkms wireguard-tools linux-headers-$(uname -r) -y")
# os.system("modprobe wireguard && lsmod | grep wireguard")

# Enable FORWARD
with open('/etc/sysctl.conf', 'r+') as f:
    content = f.read()
    f.seek(0)
    f.write(content.replace('#net.ipv4.ip_forward=1', 'net.ipv4.ip_forward=1'))

os.system("sysctl -p")

# Create keys
os.system('umask 077')
os.system('wg genkey | tee server_private_key | wg pubkey > server_public_key')
os.system("wg genkey | tee client_private_key_1 | wg pubkey > client_public_key_1")
os.system("wg genkey | tee client_private_key_2 | wg pubkey > client_public_key_2")
os.system("wg genpsk > psk_client_1")
os.system("wg genpsk > psk_client_2")

# Server
with open('server_private_key', 'r') as f:
    PRIVATE_KEY_SERVER = f.readline()
with open('server_public_key', 'r') as f:
    PUBLIC_KEY_SERVER = f.readline()

# Client 1
with open('client_private_key_1', 'r') as f:
    PRIVATE_KEY_CLIENT_1 = f.readline()
with open('client_public_key_1', 'r') as f:
    PUBLIC_KEY_CLIENT_1 = f.readline()
with open('psk_client_1', 'r') as f:
    PSK_CLIENT_1 = f.readline()

# Client 2
with open('client_private_key_2', 'r') as f:
    PRIVATE_KEY_CLIENT_2 = f.readline()
with open('client_public_key_2', 'r') as f:
    PUBLIC_KEY_CLIENT_2 = f.readline()
with open('psk_client_2', 'r') as f:
    PSK_CLIENT_2 = f.readline()

# Save ip address
os.system("ip addr show " + INTERFACE + " | grep \"inet\\b\" | awk '{print $2}' | cut -d/ -f1 > ip")
with open('ip', 'r') as f:
    SERVER_IP_ADDRESS = f.readline()


# Delete file keys
os.system('shred -z -n 64 server_private_key server_public_key client_private_key_1 client_public_key_1 client_private_key_2 client_public_key_2 psk_client_1 psk_client_2 ip')
os.system('rm server_private_key server_public_key client_private_key_1 client_public_key_1 client_private_key_2 client_public_key_2 psk_client_1 psk_client_2 ip -f')

# Create config
with open('/etc/wireguard/wg0.conf', 'w') as f:
    # [Interface]
    f.write('[Interface]\n')
    f.write(f"PrivateKey = {PRIVATE_KEY_SERVER}")
    f.write(f"Address = {ADDRESS}\n")
    f.write(f"PostUp = iptables -I INPUT -p udp --dport {WG_PORT} -j ACCEPT\n")
    f.write(f"PostUp = iptables -I FORWARD -i {INTERFACE} -o wg0 -j ACCEPT\n")
    f.write(f"PostUp = iptables -t nat -A POSTROUTING -o {INTERFACE} -j MASQUERADE\n")
    f.write(f"PostDown = iptables -D INPUT -p udp --dport {WG_PORT} -j ACCEPT\n")
    f.write(f"PostDown = iptables -D FORWARD -i {INTERFACE} -o wg0 -j ACCEPT\n")
    f.write(f"PostDown = iptables -D FORWARD -i wg0 -j ACCEPT\n")
    f.write(f"PostDown = iptables -t nat -D POSTROUTING -o {INTERFACE} -j MASQUERADE\n")
    f.write(f"ListenPort = {WG_PORT}\n")
    # f.write(f"PostUp = ip6tables -I FORWARD -i wg0 -j ACCEPT\n")
    # f.write(f"PostUp = ip6tables -t nat -A POSTROUTING -o ens3 -j MASQUERADE\n")
    # f.write(f"PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT\n")
    # f.write(f"PostDown = ip6tables -t nat -D POSTROUTING -o {INTERFACE} -j MASQUERADE\n")
    f.write('\n')

    # [Peer]
    f.write('[Peer]\n')
    f.write(f"PublicKey = {PUBLIC_KEY_CLIENT_1}")
    f.write(f"PresharedKey = {PSK_CLIENT_1}")
    f.write(f"AllowedIPs = {CLIENT_1_ADDRESS}\n")

    f.write('[Peer]\n')
    f.write(f"PublicKey = {PUBLIC_KEY_CLIENT_2}")
    f.write(f"PresharedKey = {PSK_CLIENT_2}")
    f.write(f"AllowedIPs = {CLIENT_2_ADDRESS}\n")


# Start wg server
os.system('chmod 600 /etc/wireguard/wg0.conf')
os.system('systemctl enable wg-quick@wg0.service')
os.system('systemctl restart wg-quick@wg0.service')


# ----------------------- [NBOUND DNS Server] -----------------------
# Install unbound DNS
print("[START INSTALL NBOUND DNS SERVER]")
os.system("apt install unbound unbound-host -y")

# Get DNS list servers:
os.system("curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache")

# ----------------------- [PI-HOLE] -----------------------
# Install Pi-hole
print("[START INSTALL PI-HOLE]")
os.system("apt install curl -y")
os.system("curl -sSL https://install.pi-hole.net | bash")

# Create config pi-hole.conf
with open('/etc/unbound/unbound.conf.d/pi-hole.conf', 'w') as f:
    # [Interface]
    f.write(
    f"""server:
         # if no logfile is specified, syslog is used
         # logfile: "/var/log/unbound/unbound.log"
         verbosity: 1
         port: {DNS_PORT}

         do-ip4: yes
         do-udp: yes
         do-tcp: yes

         # may be set to yes if you have IPv6 connectivity
         do-ip6: yes

         # use this only when you downlaoded the list of primary root servers
         root-hints: "/var/lib/unbound/root.hints"

         # respond to DNS requests on all interfaces
         interface: 0.0.0.0
         max-udp-size: 3072

         # IPs authorised to access the DNS Server
         access-control: 0.0.0.0/0                 refuse
         access-control: 127.0.0.1                 allow
         access-control: {CLIENT_1_DNS_ADDRESS}    allow
         access-control: {CLIENT_2_DNS_ADDRESS}    allow

         hide-identity: yes
         hide-version: yes

         harden-glue: yes
         harden-dnssec-stripped: yes
         harden-referral-path: yes

         # add an unwanted reply threshold to clean the cache and avoid, when possible, DNS poisoning
         unwanted-reply-threshold: 10000000
         use-caps-for-id: no

         # reduce EDNS reassembly buffer size
         edns-buffer-size: 1472

         # TTL bounds for cache
         cache-min-ttl: 3600
         cache-max-ttl: 86400

         prefetch: yes
         prefetch-key: yes
         num-threads: 1
         so-rcvbuf: 1m

         # ensure privacy of local IP ranges
         private-address: 192.168.0.0/16
         private-address: 169.254.0.0/16
         private-address: 172.16.0.0/12
         private-address: 10.0.0.0/8
         private-address: fd00::/8
         private-address: fe80::/10
    """)


# hosts
os.system("curl -Ssl https://raw.githubusercontent.com/LukeSmithxyz/etc/master/ips >> /etc/hosts")


with open('/etc/pihole/setupVars.conf', 'w') as f:
    f.write(f"""
        PIHOLE_INTERFACE=wg0
        QUERY_LOGGING=true
        INSTALL_WEB_SERVER=true
        INSTALL_WEB_INTERFACE=true
        LIGHTTPD_ENABLED=true
        CACHE_SIZE=10000
        DNS_FQDN_REQUIRED=true
        DNS_BOGUS_PRIV=true
        DNSMASQ_LISTENING=single
        WEBPASSWORD=173af653133d964edfc16cafe0aba33c8f500a07f3ba3f81943916910c257705
        BLOCKING_ENABLED=true
        DNSSEC=true
        REV_SERVER=false
        PIHOLE_DNS_1=127.0.0.1#{DNS_PORT}
    """)

# Set password Pi-hole
print("[SET PASSWORD FOR PI-HOLE]")
os.system("pihole -a -p")

# ----------------------- [IPTABLES/NFTABLES] -----------------------
print("[SETTING NFTABLES]")

# Затем правила для рекурсивного DNS:
# os.system(f"iptables -A INPUT -s {CLIENT_DNS_ADDRESS} -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT")
# os.system(f"iptables -A INPUT -s {CLIENT_DNS_ADDRESS} -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT")
#
# # Доступ к админ панели только через vpn
# os.system(f"iptables -A INPUT -s {CLIENT_DNS_ADDRESS[:-3]} -p tcp --dport 80 -j ACCEPT")
# os.system("iptables -A INPUT -p tcp --dport 80 -j DROP")
# # os.system("sudo netfilter-persistent save")
#
#
# # Save iptables
# os.system("echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections")
# os.system("echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections")
#
# os.system("apt install iptables-persistent -y")
# os.system("systemctl enable netfilter-persistent")
# os.system("netfilter-persistent save")


# Подключение к серверу только по vpn
# iptables -A INPUT -s 10.8.0.2 -p tcp --dport 42567 -j ACCEPT
# iptables -A INPUT -p tcp --dport 42567 -j DROP
# ip6tables -P INPUT DROP && ip6tables -P FORWARD DROP && ip6tables -P OUTPUT DROP
# sudo netfilter-persistent save

# ----------------------- [LOG] -----------------------
print("[WIREGUARD, PI-HOLE, NBOUND INSTALLED]")
print("SERVER IP: " + SERVER_IP_ADDRESS)
print("PORT: " + WG_PORT)
print("PUBLIC_KEY_SERVER: " + PUBLIC_KEY_SERVER)
print("DNS SERVER: " + ADDRESS[:-3])
print("-----------------------------------------------------------------------")
print("CLIENT 1")
print("PRIVATE_KEY_CLIENT: " + PRIVATE_KEY_CLIENT_1)
print("PSK_CLIENT: " + PSK_CLIENT_1)
print("-----------------------------------------------------------------------")
print("CLIENT 2")
print("PRIVATE_KEY_CLIENT: " + PRIVATE_KEY_CLIENT_2)
print("PSK_CLIENT: " + PSK_CLIENT_2)

# Reboot
os.system('systemctl reboot')
